package dao;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;

import util.HibernateUtil;
import vo.OrganizationUnitVO;
import vo.OrganizationVO;
import vo.OrganizationValueVO;
import entity.Organization;
import entity.OrganizationUnit;
import entity.OrganizationValues;
import entity.StrategicPerspective;
import entity.Usuario;

public class OrganizationDAO {
	
	public List<OrganizationVO> listOrganization() {
		Session sessao = HibernateUtil.getSession();		
		Criteria criterios = sessao.createCriteria(Organization.class);
		
		List<?> lista = criterios.list();
		List<OrganizationVO> listaOrganizacao = new ArrayList<OrganizationVO>();
		
		for(Object obj:lista){
			Organization org = (Organization) obj;
			OrganizationVO vo = new OrganizationVO();
			
			vo.setId(org.getId());
			vo.setNome(org.getName());
			vo.setMissao(org.getMission());
			vo.setVisao(org.getVision());
			vo.setNomeAdministrador(org.getAdmin().getNome());
			vo.setIdAdmin(org.getAdmin().getId());
			
			List<OrganizationUnitVO> listaUnidadeOrganizacao = new ArrayList<OrganizationUnitVO>();			
			for(OrganizationUnit ou: org.getListaOrganizationUnit()){
				OrganizationUnitVO ouVO = new OrganizationUnitVO();
				ouVO.setLevel(ou.getLevel());
				ouVO.setNome(ou.getName());
				listaUnidadeOrganizacao.add(ouVO);
			}
			
			List<OrganizationValueVO> listaValoresOrganizacao = new ArrayList<OrganizationValueVO>();
			for(OrganizationValues ov:org.getOrganizationValuesList()){
				OrganizationValueVO ovVO = new OrganizationValueVO();
				ovVO.setValue(ov.getValueOrganization());
				ovVO.setId(ov.getId());
				ovVO.setPosition(ov.getPosition());
				listaValoresOrganizacao.add(ovVO);
			}
			
			vo.setListaOrganizationUnit(listaUnidadeOrganizacao);
			vo.setListaValoresOrganizacao(listaValoresOrganizacao);
			
			listaOrganizacao.add(vo);
		}
		
		sessao.close();
		return listaOrganizacao;
	}
	
	public void saveOrganization(OrganizationVO vo, List<OrganizationValueVO> list) {
		Session sessao = HibernateUtil.getSession();
		Transaction tx = sessao.beginTransaction();
		try{
			saveOrganizationInternal(vo, list, sessao);
			tx.commit();
			sessao.close();
		}
		catch(Exception e){
			e.printStackTrace();
			tx.rollback();
			sessao.close();
		}
	}

	public void saveOrganizationInternal(OrganizationVO vo, List<OrganizationValueVO> list, Session sessao) throws Exception{
		Organization org;
		boolean insert = false;
		
		if (vo.getId() > 0)
			org = (Organization)sessao.load(Organization.class, vo.getId());
		else{
			org = new Organization();
			org.setOrganizationValuesList(new ArrayList<OrganizationValues>());
			org.setPerspectives(new ArrayList<StrategicPerspective>());
			org.setListaOrganizationUnit(new ArrayList<OrganizationUnit>());
			insert = true;
		}
		
		org.setName(vo.getNome());
		org.setMission(vo.getMissao());
		org.setVision(vo.getVisao());
		
		UsuarioDAO usuarioDAO = new UsuarioDAO();
		Usuario u = usuarioDAO.getUser(vo.getIdAdmin(), sessao);
		
		org.setAdmin(u);
		
		for(OrganizationValueVO ovVO:vo.getListaValoresOrganizacao()){
			OrganizationValues ov;
			
			if (ovVO.getId() > 0){
				ov = (OrganizationValues) sessao.load(OrganizationValues.class, ovVO.getId());
				org.getOrganizationValuesList().remove(ov);
			}
			else{
				ov = new OrganizationValues();
			}
			
			ov.setOrganization(org);
			ov.setValueOrganization(ovVO.getValue());
			ov.setPosition(ovVO.getPosition());
			
			org.getOrganizationValuesList().add(ov);
		}
		
		for(OrganizationValueVO ovVO:list){
			OrganizationValues ov;
			
			if (ovVO.getId() > 0){
				ov = (OrganizationValues) sessao.load(OrganizationValues.class, ovVO.getId());
				org.getOrganizationValuesList().remove(ov);
			}
		}
		
		if (insert) {
			org.getPerspectives().add(createPerspective("Clientes", "Clientes", "C", org));
			org.getPerspectives().add(createPerspective("Financeira", "Financeira", "F", org));
			org.getPerspectives().add(createPerspective("Processos Internos", "Processos Internos", "P", org));
			org.getPerspectives().add(createPerspective("Crescimento", "Crescimento", "CR", org));
		}
		
		sessao.saveOrUpdate(org);
	}

	private StrategicPerspective createPerspective(String name, String description, String acronym, Organization org) {
		StrategicPerspective sp = new StrategicPerspective();
		sp.setName(name);
		sp.setDescription(description);
		sp.setAcronym(acronym);
		sp.setOrganization(org);
		
		return sp;
	}

	@SuppressWarnings("unchecked")
	public OrganizationVO getOrganization(int organizacaoId) {
		Session sessao = HibernateUtil.getSession();
		Organization o = (Organization) sessao.load(Organization.class, organizacaoId);
		
		OrganizationVO vo = new OrganizationVO();
		vo.setId(o.getId());
		vo.setNome(o.getName());
		vo.setMissao(o.getMission());
		vo.setVisao(o.getVision());
		vo.setNomeAdministrador(o.getAdmin().getNome());
		vo.setIdAdmin(o.getAdmin().getId());
		
		List<OrganizationUnitVO> listaUnidadeOrganizacao = new ArrayList<OrganizationUnitVO>();			
		for(OrganizationUnit ou: o.getListaOrganizationUnit()){
			OrganizationUnitVO ouVO = new OrganizationUnitVO();
			ouVO.setLevel(ou.getLevel());
			ouVO.setNome(ou.getName());
			listaUnidadeOrganizacao.add(ouVO);
		}
		
		List<OrganizationValueVO> listaValoresOrganizacao = new ArrayList<OrganizationValueVO>();
		for(OrganizationValues ov:o.getOrganizationValuesList()){
			OrganizationValueVO ovVO = new OrganizationValueVO();
			ovVO.setValue(ov.getValueOrganization());
			ovVO.setId(ov.getId());
			ovVO.setPosition(ov.getPosition());
			listaValoresOrganizacao.add(ovVO);
		}
		
		Collections.sort(listaValoresOrganizacao, new Comparator(){
			public int compare(Object obj0, Object obj1) {
				OrganizationValueVO o0 = (OrganizationValueVO) obj0;
				OrganizationValueVO o1 = (OrganizationValueVO) obj1;
				
				if (o0.getPosition() > o1.getPosition())
					return 1;
				else if (o0.getPosition() == o1.getPosition())
					return 0;
				else
					return -1;
			}
		});
		
		vo.setListaOrganizationUnit(listaUnidadeOrganizacao);
		vo.setListaValoresOrganizacao(listaValoresOrganizacao);
		
		sessao.close();
		return vo;
	}
}
